import Vue from 'vue'
const temp = uni.request
const sendUrl = 'https://api.yeshaojun.com/v1/error/catchError'
class CatchError {
	constructor(options) {
	    // options sendUrl 发送服务器地址 目前就一个参数，后续再补充
		this.options = options
    this.$request = options.request || {}
    this.$vue = options.vue || {}
		// 添加请求监听
		this._catchRequestError()
		// #ifdef MP-WEIXIN
		    this._catchEventError()
		// #endif
		this._catchVueError()
	}
	// 捕获request返回状态不为200的异常
	_catchRequestError() {
		const that = this
		Object.defineProperties(uni, {
		  'request': {
			value: function(args) {
			  // wx.request(args)
			  temp.apply(uni, [{
				...args,
				success: (res) => {
				  args.success && args.success.apply(args, [res])
          if (that._isNeedRequestCatch(args, res.data)) {
            const page = getCurrentPages()
            let userInfo = uni.getStorageSync('userInfo') || ''
            if (res.statusCode !==200) {
            	CatchError.notify({
            		type: 'request success',
            		name: that.options.name || '',
            		content: JSON.stringify({
            			...args,
            			error: res.data,
            			route: page,
            			userInfo
            		})
            	})
            } 
          }
				},
				fail: (err) => {
					CatchError.notify({
						type: 'request fail',
						name: that.options.name || '',
						content: JSON.stringify({
							...args,
							error: err,
              route: page,
              userInfo: uni.getStorageSync('userInfo-' + wxInfo.miniProgram.appId)
						})
					})
				}
			  }])
			},
			configurable: true,
			enumerable: true
		  }
		})
	}
	
	// 捕获onError事件异常以及api请求异常
	_catchEventError() {
		const that = this
		uni.onError((err) => {
			CatchError.notify({
				type: 'OnError',
				name: that.options.name || '',
				content: JSON.stringify(err)
			})
		})
	}

	// 捕获vue全局异常
	_catchVueError() {
		const that = this
		Vue.config.errorHandler = (err, vm, info) => {
			// console.warn('vue vue', err, vm, info)
			if(this._isNeedVueCatch(info)) {
				CatchError.notify({
					type: 'Vue Error',
					name: that.options.name || '',
					content: JSON.stringify({
						err: JSON.stringify(err),
						route: vm.route,
						info: info
					})
				})
			}

		}
	}

  // 判断是否需要捕获接口请求异常
  _isNeedRequestCatch (requestInfo, requestResult) {
    let result = true
    console.warn('this.$request.urls', this.$request)
    if (this.$request.urls.indexOf(requestInfo.url) !== -1 || this.$request.codes.indexOf(requestResult.errorCode)) {
      result = false
    }
    return result
  }
  
  // 判断是否需要捕获vue异常
  _isNeedVueCatch (info) {
    let result = true
    if (this.$vue.info.indexOf(info)!==-1) {
      result = false
    }
    return result
  }
	// 单例模式
	static _getInstance(options) {
	  var instance = null;
	  return () => {
		if (!instance) {
		  instance = new CatchError(options)
		}
		return instance
	  }
	}
	// 初始化
	static init(options) {
		if (options.isOpen) {
			CatchError._getInstance(options)()
		}
	}
	// 上报异常
	static notify(options) {
		temp({
			url: sendUrl,
			method: 'POST',
			data: options
		})
	}
}

// const Error = {}
export default CatchError
